﻿using Bookify.Application.Abstractions.Caching;
using Bookify.Domain.Users;
using Microsoft.EntityFrameworkCore;

namespace Bookify.Infrastructure.Authorization
{
    internal sealed class AuthorizationService
    {
        private readonly ApplicationDbContext _dbContext;
        private readonly ICacheService _cacheService;

        public AuthorizationService(ApplicationDbContext dbContext, ICacheService cacheService)
        {
            _dbContext = dbContext;
            _cacheService = cacheService;
        }

        public async Task<UserRolesResponse> GetRolesForUserAsync(string identityId)
        {
            string cacheKey = $"auth:roles-{identityId}";
            UserRolesResponse? catchedRoles = await _cacheService.GetAsync<UserRolesResponse>(cacheKey);

            if(catchedRoles != null)
            {
                return catchedRoles;
            }

            var roles = await _dbContext.Set<User>()
                .Where(x => x.IdentityId == identityId)
                .Select(u => new UserRolesResponse
                {
                    UserId = u.Id,
                    Roles = u.Roles.ToList()
                })
                .FirstAsync();
            
            await _cacheService.SetAsync(cacheKey, roles);

            return roles;
        }

        public async Task<HashSet<string>> GetPermissionsForUserAsync(string identityId)
        {
            string cacheKey = $"auth:permissions-{identityId}";
            HashSet<string>? catchedPermissions = await _cacheService.GetAsync<HashSet<string>>(cacheKey);
            
            if(catchedPermissions != null)
            {
                return catchedPermissions;
            }

            var permissions = await _dbContext.Set<User>()
                .Where(x => x.IdentityId == identityId)
                .SelectMany(u => u.Roles.Select(r=> r.Permissions))
                .FirstAsync();

            var permissionsSet = permissions.Select(p => p.Name).ToHashSet();

            await _cacheService.SetAsync(cacheKey, permissionsSet);

            return permissionsSet;
        }

        
    }
}
